package com.example.basecore.boot;

import com.example.basecore.core.EventHandlerAnnotation;
import com.example.basecore.event.DefaultEventBus;
import com.example.basecore.event.Event;
import com.example.basecore.event.EventHandler;
import com.example.basecore.factory.EventHandlerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.lang.annotation.Annotation;
import java.util.*;

/**
 * @author ycd0075
 * @date 2024-01-25 23:09
 */
public class EventRegistry extends BaseRegistry implements FactoryBean<DefaultEventBus>, ApplicationContextAware {

    private ApplicationContext context;

    @Override
    public DefaultEventBus getObject(){
        return new DefaultEventBus(createEventHandlerFactory(EventHandlerAnnotation.class));
    }

    @Override
    public Class<?> getObjectType() {
        return DefaultEventBus.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        this.context = context;
    }

    /**
     * @param eventHandlerType
     * @return
     */
    public EventHandlerFactory createEventHandlerFactory(Class<? extends Annotation> eventHandlerType){

        // 处理EventExecutor
        Map<String, Object> handlers = context.getBeansWithAnnotation(eventHandlerType);
        Map<Class<? extends Event>, Set<EventHandler>> handlerMap = new HashMap(handlers.size());
        if(Objects.nonNull(handlers) && handlers.size() > 0){
            handlers.forEach((k,bean)->{
                Assert.isTrue(bean instanceof EventHandler,String.format("Bean [%s:%s] is not an instance of %s", k, bean.getClass(), EventHandler.class));
                EventHandler eventHandler = (EventHandler)bean;
                AnnotationAttributes annotationAttributes = AnnotationAttributes.fromMap(createStandardAnnotationMetadata(eventHandler.getClass()).getAnnotationAttributes(eventHandlerType.getName()));
                Class<? extends Event> event = annotationAttributes.getClass(EVENTS);
                if(CollectionUtils.isEmpty(handlerMap.get(event))){
                    Set<EventHandler> eventHandlers = new HashSet();
                    eventHandlers.add(eventHandler);
                    handlerMap.put(event,eventHandlers);
                }else{
                    Set<EventHandler> eventHandlers = handlerMap.get(event);
                    eventHandlers.add(eventHandler);
                    handlerMap.put(event,eventHandlers);
                }
            });
        }
        return new EventHandlerFactory(handlerMap);
    }
}
